package database;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import event.Event;

public class EventSerializerMySQL extends EventSerializer {
	private static String DB_DRIVER_DEFAULT = "com.mysql.jdbc.Driver";
	private static String DB_CONNECTION_DEFAULT = "jdbc:mysql://localhost:3306/CEPL";
	private static String DB_USER_DEFAULT = "root";
	private static String DB_PASSWORD_DEFAULT = "cepl";

	protected EventSerializerMySQL() throws ClassNotFoundException,
			SQLException {
		if (EventSerializer.DB_CONNECTION == null)
			EventSerializer.DB_CONNECTION = DB_CONNECTION_DEFAULT;
		if (EventSerializer.DB_USER == null)
			EventSerializer.DB_USER = DB_USER_DEFAULT;
		if (EventSerializer.DB_PASSWORD == null)
			EventSerializer.DB_PASSWORD = DB_PASSWORD_DEFAULT;
		if (EventSerializer.DB_DRIVER == null)
			EventSerializer.DB_DRIVER = DB_DRIVER_DEFAULT;

		connect();
	}

	@Override
	public void storeEvent(Event e) {
		try {
			if (teller == 0) {
				String INSERT = "INSERT INTO SerializedEvents (ID, streamID, timestamp, isForwarded, isPrimitive, isCacheable, data) "
						+ " VALUES (?,?,?,?,?,?,?)";

				for (int i = 1; i < insertBatchSize; ++i) {
					INSERT += ", (?,?,?,?,?,?,?)";
				}

				prepStatement = connection.prepareStatement(INSERT);
			}

			prepStatement.setLong(teller * 7 + 1, e.getID());
			prepStatement.setLong(teller * 7 + 2, e.getStreamID());
			prepStatement.setTimestamp(teller * 7 + 3, e.getTimestamp());
			prepStatement.setBoolean(teller * 7 + 4, e.isForwarded());
			prepStatement.setBoolean(teller * 7 + 5, e.isPrimitive());
			prepStatement.setBoolean(teller * 7 + 6, e.isCacheable());
			prepStatement.setBytes(teller * 7 + 7, e.toSerializedByteArray());

			teller++;
			if (teller == insertBatchSize)
				commitInsertBatch();
		} catch (SQLException e1) {
			e1.printStackTrace();
		}
	}

	@Override
	public Event retrieveEvent(long ID) {
		Event result = null;

		try {
			try {
				if (!isConnected())
					connect();
				connection.setAutoCommit(true);
				PreparedStatement ps = connection
						.prepareStatement("SELECT * FROM SerializedEvents WHERE ID=?");
				ps.setInt(1, (int) ID);

				ResultSet rs = ps.executeQuery();
				if (rs.next()) {
					byte buf[] = rs.getBytes("data");
					result = new Event(buf);
				}
				rs.close();
				connection.setAutoCommit(false);
			} catch (ClassNotFoundException e1) {
				e1.printStackTrace();
			}
		} catch (SQLException e1) {
			e1.printStackTrace();
		}

		return result;
	}

	@Override
	public long getMaximumSerializedID() {
		long result = 0;
		try {
			try {
				if (!isConnected())
					connect();
				connection.setAutoCommit(true);
				PreparedStatement ps = connection
						.prepareStatement("SELECT MAX(ID) FROM SerializedEvents");
				ResultSet rs = ps.executeQuery();
				if (rs.next()) {
					int ID = rs.getInt(1);
					result = (long) ID;
				}
				rs.close();
				connection.setAutoCommit(false);
			} catch (ClassNotFoundException e1) {
				e1.printStackTrace();
			}
		} catch (SQLException e1) {
			e1.printStackTrace();
		}

		return result;
	}

	@Override
	public void truncateSerializedEvents() {
		try {
			try {
				if (!isConnected())
					connect();
				connection.setAutoCommit(true);
				Statement stat = connection.createStatement();
				stat.execute("TRUNCATE SerializedEvents");
				connection.setAutoCommit(false);
			} catch (ClassNotFoundException e1) {
				e1.printStackTrace();
			}
		} catch (SQLException e1) {
			e1.printStackTrace();
		}
	}

	@Override
	public void createTable() {
		dropTable();

		try {
			try {
				if (!isConnected())
					connect();
				connection.setAutoCommit(true);
				Statement stat = connection.createStatement();
				stat.executeUpdate("CREATE TABLE SerializedEvents("
						+ "ID BIGINT  not null, "
						+ "streamID BIGINT not null, "
						+ "timestamp TIMESTAMP not null, "
						+ "isForwarded BOOLEAN not null, "
						+ "isPrimitive BOOLEAN not null, "
						+ "isCacheable BOOLEAN not null, "
						+ "data BLOB not null" + ")");

				connection.setAutoCommit(false);
			} catch (ClassNotFoundException e1) {
				e1.printStackTrace();
			}
		} catch (SQLException e1) {
			e1.printStackTrace();
		}
	}

	@Override
	public void dropTable() {
		try {
			try {
				if (!isConnected())
					connect();
				connection.setAutoCommit(true);
				Statement stat = connection.createStatement();
				stat.executeUpdate("DROP TABLE IF EXISTS SerializedEvents");

				connection.setAutoCommit(false);
			} catch (ClassNotFoundException e1) {
				e1.printStackTrace();
			}
		} catch (SQLException e1) {
			e1.printStackTrace();
		}
	}
}
